package com.jiazhong.front.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiazhong.commons.Mapper.BookMapper;
import com.jiazhong.commons.Mapper.StockMapper;
import com.jiazhong.commons.Util.JsonResult;
import com.jiazhong.commons.Util.ResultTool;
import com.jiazhong.commons.bean.Book;
import com.jiazhong.commons.bean.ShoppingCart;
import com.jiazhong.commons.bean.Stock;
import com.jiazhong.commons.config.JwtConfig;
import com.jiazhong.commons.exception.GwcIsEmptyException;
import com.jiazhong.commons.exception.StockFailException;
import com.jiazhong.front.service.ShoppingCartService;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private BookMapper bookMapper;
    @Resource
    private StockMapper stockMapper;
    // 整体购物车的key
    public static final String GWC_KEY = "GWC_KEY";
    public static final String GWC_GEREN_PREFIX = "GWC_PREFIX_";

    @Override
    public JsonResult add(String token, String bookId){
        //获取用户id
        Object userid = JwtConfig.parseJWT(token).get("id");
        //获取用户的购物车
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        Object itGwcKey = forHash.get(GWC_KEY, userid);
        String listKey = itGwcKey + "";
        if (itGwcKey == null){
            listKey = GWC_GEREN_PREFIX + userid;
        }
        List<String> itGwc = forList.range(listKey, 0, -1);
        log.info("获取到{}用户的购物车：{}",userid,itGwc);
        //3.根据购物车的状态判断时加入购物车还是修改数量
        AtomicBoolean flag = new AtomicBoolean(false);
        log.info("开始判断{}是否在购物车中",bookId);
        for (int i = 0; i < itGwc.size(); i++) {
            String e = itGwc.get(i);
            //根据bookId判断是不是已经在购物车里
            boolean b = e.startsWith(bookId);
            //在购物车里
            if (b){
                flag.set(true);
                int firsIndex = e.indexOf("#");
                int lastIndex = e.lastIndexOf("#");
                int number = Integer.parseInt(e.substring(firsIndex+1,lastIndex));
                number++;
                forList.set(listKey,i,bookId + '#' + number + "#" + 2);
                log.info("{}图书存在购物车中，更新数量，现有数量是：{}",bookId,number);
                break;
            }
        }
        //购物车中不存在该商品
        if (!flag.get()){
            log.info("{}商品不存在购物车中，添加",bookId);
            //将商品放入购物车里
            String val = bookId + "#" + 1 + "#" +0;
            forList.rightPush(listKey,val);
        }
        forHash.put(GWC_KEY,userid,listKey);
        return ResultTool.success("success");
    }

    @Override
    public JsonResult find(String token) {
        //获取用户id
        Claims claims = JwtConfig.parseJWT(token);
        String userid = claims.get("id").toString();
        //从redis获取购物车
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        //在大的容器中根据用户id获取到用户的购物车listKey
        Object listKey = forHash.get(GWC_KEY, userid);
        if (Objects.isNull(listKey)){
            throw new GwcIsEmptyException("用户购物车为空");
        }
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        List<String> gwc = forList.range(listKey.toString(), 0, 1);
        // 3. 将gwc容器中的内容放入到list集合中
        // id#number
        // image name price publisher number
        //通过id获取到image name price publisher
        ArrayList<ShoppingCart> list = new ArrayList<>();
        gwc.forEach(e->{
            //从最后一个#号分隔开图书的id和number
            int firsIndex = e.indexOf("#");
            int lastIndex = e.lastIndexOf("#");
            int number = Integer.parseInt(e.substring(firsIndex+1,lastIndex));
            String bookId = e.substring(0, firsIndex);
            int state = Integer.parseInt(e.substring(lastIndex+1));
            if (state < 3) {
                //封装起来
                ShoppingCart cart = new ShoppingCart();
                cart.setNumber(number);
                cart.setBookId(bookId);
                Book book = bookMapper.selectById(bookId);
                cart.setName(book.getName());
                cart.setPrice(book.getPrice());
                cart.setImageName(book.getImageName());
                cart.setPublisher(book.getPublisher());
                list.add(cart);
            }
        });
        return ResultTool.success(list);
    }

    @Override
    public JsonResult changeNumber(String token, String bookId, int change) {
        String userid = JwtConfig.parseJWT(token).get("id").toString();
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        Object listKey = forHash.get(GWC_KEY, userid);
        if (Objects.isNull(listKey)){
            throw new GwcIsEmptyException("用户购物车为空");
        }
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        List<String> gwc = forList.range(listKey.toString(), 0, -1);
        final int[] index = {0};
        gwc.forEach(e -> {
            boolean b = e.startsWith(bookId);
            if (b) {
                int firsIndex = e.indexOf("#");
                int lastIndex = e.lastIndexOf("#");
                int number = Integer.parseInt(e.substring(firsIndex+1,lastIndex));
                number = number + change;
                int state = Integer.parseInt(e.substring(lastIndex+1));
                QueryWrapper<Stock> wrapper = new QueryWrapper<>();
                wrapper.eq("book_id", bookId);
                Stock stock = stockMapper.selectOne(wrapper);
                if (number > stock.getNumber()) {
                    throw new StockFailException("库存不充足");
                } else if (number < 1) {
                    throw new StockFailException("商品数量不能小于1");
                }
                if (state == 0) {
                    forList.set(listKey.toString(), index[0], bookId + "#" + number + "#" + 0);
                } else {
                    forList.set(listKey.toString(), index[0], bookId + "#" + number + "#" + 2);
                }
            }
            index[0]++;
        });
        return ResultTool.success("success");
    }

    @Override
    public JsonResult changeNumber2(String token, String bookId, int change) {
        String userid = JwtConfig.parseJWT(token).get("id").toString();
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        Object listKey = forHash.get(GWC_KEY, userid);
        if (Objects.isNull(listKey)){
            throw new GwcIsEmptyException("用户购物车为空");
        }
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        List<String> gwc = forList.range(listKey.toString(), 0, -1);
        final int[] index = {0};
        gwc.forEach(e -> {
            boolean b = e.startsWith(bookId);
            if (b) {
                int firsIndex = e.indexOf("#");
                int lastIndex = e.lastIndexOf("#");
                int number = Integer.parseInt(e.substring(firsIndex+1,lastIndex));
                number = change;
                int state = Integer.parseInt(e.substring(lastIndex+1));
                QueryWrapper<Stock> wrapper = new QueryWrapper<>();
                wrapper.eq("book_id", bookId);
                Stock stock = stockMapper.selectOne(wrapper);
                if (number > stock.getNumber()) {
                    throw new StockFailException("库存不充足");
                } else if (number < 1) {
                    throw new StockFailException("商品数量不能小于1");
                }
                if (state == 0) {
                    forList.set(listKey.toString(), index[0], bookId + "#" + number + "#" + 0);
                } else {
                    forList.set(listKey.toString(), index[0], bookId + "#" + number + "#" + 2);
                }
            }
            index[0]++;
        });
        return ResultTool.success("success");
    }

    @Override
    public JsonResult remove(String token, String bookId) {
        String userid = JwtConfig.parseJWT(token).get("id").toString();
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        Object listKey = forHash.get(GWC_KEY, userid);
        if (Objects.isNull(listKey)){
            throw new GwcIsEmptyException("用户购物车为空");
        }
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        List<String> gwc = forList.range(listKey.toString(), 0, -1);
        for (int i = 0; i < gwc.size(); i++) {
            String e = gwc.get(i);
            boolean b = e.startsWith(bookId);
            if (b){
                forList.set(listKey.toString(),i,bookId + "#" + 666 + "#" + 3);
                //forList.remove(listKey.toString(),1,e);
                break;
            }
        }
        return ResultTool.success("success");
    }

    @Override
    public JsonResult removeBatch(String token, String... bookId) {
        String userid = JwtConfig.parseJWT(token).get("id").toString();
        HashOperations<String, Object, Object> forHash = stringRedisTemplate.opsForHash();
        Object listKey = forHash.get(GWC_KEY, userid);
        if (Objects.isNull(listKey)){
            throw new GwcIsEmptyException("用户购物车为空");
        }
        ListOperations<String, String> forList = stringRedisTemplate.opsForList();
        List<String> gwc = forList.range(listKey.toString(), 0, -1);
        for (int i = 0; i < gwc.size(); i++) {
            String e = gwc.get(i);
            for (int j = 0; j < bookId.length; j++) {
                boolean b = e.startsWith(bookId[j]);
                if (b){
                    forList.set(listKey.toString(),i,bookId[j] + "#" + 666 + "#" + 3);
                    //forList.remove(listKey.toString(),1,e);
                    break;
                }
            }
        }
        return ResultTool.success("success");
    }
}
